package func.rank;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

import func.equ.Equation;

import nodes.Node;

public class EquRankFunction implements RankFunction<Double> {
	
	private Double[][] values;
	private Equation<Double> equ;

	public EquRankFunction(Double[][] values, Equation<Double> equ) {
		this.values = values;
		this.equ = equ;
	}

	@Override
	public void sortByRank(ArrayList<Node<Double>> pop) {
		Comparator<Node<Double>> comp = new 
			Comparator<Node<Double>>() {
				public int compare(Node<Double> n1, Node<Double> n2) {
					double score1 = applyScoreFunction(n1);
					double score2 = applyScoreFunction(n2);
					if(score1 == score2)
						return 0;
					else if(score1 > score2)
						return 1;
					else
						return -1;
				}
			};
		Collections.sort(pop, comp);
	}

	@Override
	public double applyScoreFunction(Node<Double> n) {
		double dif = 0;
		for(int i = 0; i < values.length; i++) {
			Double[] row = values[i];
			Double[] param = new Double[row.length + 1];
			for(int j = 0; j < row.length; j++)
				param[j] = row[j];
			
			double eval = n.evaluate(row);
			if(Double.isNaN(eval)) {
				dif = Double.MAX_VALUE;
				//System.out.println("----- Failed Once -----");
				break;
			}
			
			param[param.length - 1] = eval;
			
			double result = equ.getResult(param);
			if(Double.isNaN(result)) {
				dif = Double.MAX_VALUE;
				//System.out.println("----- Failed Twice -----");
				break;
			}
			
			dif = dif + Math.abs(result);
		}
		
		if(dif < 0)
			dif = Double.MAX_VALUE;
		
		return dif;
	}
}
